package org.stan.beanvalidator.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
import org.stan.beanvalidator.annotation.BeanValidate;
import org.stan.beanvalidator.factory.AnnotationFactoty;
import org.stan.beanvalidator.factory.BeanValidateFactory;
import org.stan.beanvalidator.utils.ValidatorUtil;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 切面类
 * @author src
 * @Date 2020/6/19 13:45
 * @version 1.0
 */
@Aspect
@Component
@ComponentScan("com.*")
public class BeanValidatorAspectFactory {
    /**
     * 扫描com包下所有类下所有方法
     * @author src
     * @Date 2020/6/19 13:51
     * @version 1.0
     */
    @Before("execution(* com..controller..*.*(..))")
    public void before(JoinPoint joinPoint)throws Exception{
        System.out.println("开始校验目标Bean...");
        ValidatorUtil.refreshResult(); // 初始化校验失败集合
        Long startTime = System.currentTimeMillis();
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Method method = ms.getMethod();
        BeanValidate beanValidate = method.getAnnotation(BeanValidate.class);
        if(null==beanValidate){return;}
        Class<?> clazz = beanValidate.clazz();
        // 获取切入点的参数名称和值
        Object[] paramValues = joinPoint.getArgs();
        for(Object o:paramValues) {
            // 当切入点获取的参数对象和参数对象一致时
            if (clazz.isInstance(o)) {
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    /** 校验器策略工厂 **/
                    BeanValidateFactory.getValidator(ValidatorUtil.getAnnotation(field)).beanValidate(field,o,clazz,beanValidate);
                }
            }
        }
        // 记录校验失败结果
        ValidatorUtil.getValidateResult();
        long time = (System.currentTimeMillis() - startTime);
        System.out.println("校验目标Bean ["+clazz.getName()+"] 完成，共耗时：" + time + " 毫秒!");
    }
}
